package com.taing.sample.web;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.URL;

import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring;

/**
 * @Author tianyi
 * @Description // todo
 * @Date 2023 - 02 - 09
 **/
@Component
public class GraphQLProvider {

    private GraphQL graphQL;

    @Bean
    public GraphQL graphQL() {
        // 这个GraphQL实例通过使用@Bean注解的GraphQL()方法作为Spring Bean暴露出去。
        return graphQL;
    }

    @PostConstruct
    public void init() throws IOException {
        /**
         *我们使用Guava资源从类路径读取文件，然后创GraphQLSchema和GraphQL实例。
         */
        URL url = Resources.getResource("graphql/schema.graphqls");
        String sdl = Resources.toString(url, Charsets.UTF_8);
        // 我们还需要做的是实现buildSchema方法，它创建GraphQLSchema实例，并连接代码来获取数据:
        GraphQLSchema graphQLSchema = buildSchema(sdl);
        // GraphQL Java Spring适配器将使用该GraphQL实例，使我们的schema可以通过默认url/GraphQL进行HTTP访问。
        this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();

    }

    private GraphQLSchema buildSchema(String sdl) {
        /**
         * 这个GraphQL实例通过使用@Bean注解的GraphQL()方法作为Spring Bean暴露出去。
         * GraphQL Java Spring适配器将使用该GraphQL实例，使我们的schema可以通过默认url/GraphQL进行HTTP访问。
         */
        // TypeDefinitionRegistry是schema文件的解析版本。
        // SchemaGenerator将TypeDefinitionRegistry与RuntimeWiring结合起来，实际生成GraphQLSchema。
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }

    @Autowired
    private GraphQLDataFetchers graphQLDataFetchers;

    private RuntimeWiring buildWiring() {
        // buildRuntimeWiring使用graphQLDataFetchersbean来注册两个Datafetchers:
        return RuntimeWiring.newRuntimeWiring()
                // 一个是检索具有特定ID的图书。
                .type(newTypeWiring("Query")
                        .dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher()))
                // 一个是检索具有特定ID的图书。
                .type(newTypeWiring("Book")
                        .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher()))
                .build();
    }
}
